using UnityEngine;
using System.Collections.Generic;
using System.Linq;

public class InitMaze : Singleton<InitMaze>
{
    [Header("迷宫配置")]
    /// <summary>
    /// 放置所有的柱子
    /// </summary>
    [HideInInspector] public GameObject WallColumnParent;
    /// <summary>
    /// 放置所有的房间
    /// </summary>
    [HideInInspector] public GameObject RoomParent;
    /// <summary>
    /// 迷宫的一个房间预设
    /// </summary>
    public GameObject RoomPrefab;
    /// <summary>
    /// 柱子预设
    /// </summary>
    public GameObject WallColumnPrefab;
    /// <summary>
    /// 墙壁预设
    /// </summary>
    public GameObject WallPrefab;
    public int BuildRow;
    public int BuildColumn;

    /// <summary>
    /// 房间坐标--房间 的字典
    /// </summary>
    public Dictionary<string, Room> RoomDict = new Dictionary<string, Room>();
    /// <summary>
    /// 保存所有房间
    /// </summary>
    public List<Room> RoomList = new List<Room>();
    int wallYOffset;
    int wallColumnYOffset;
    // 创建封闭的迷宫房间
    public void CreateMaze()
    {
        wallYOffset = (int)(WallPrefab.transform.localScale.y * 0.5f);
        wallColumnYOffset = (int)(WallColumnPrefab.transform.localScale.y * 0.5f);
        // 生成柱子的位置
        Vector3 wallColumnPos = new Vector3(0, wallColumnYOffset, 0);

        for (int i = 0; i < BuildRow; i++)
        {
            wallColumnPos.x = i * 5;
            for (int j = 0; j < BuildColumn; j++)
            {
                wallColumnPos.z = j * 5;
                CreateWallColumn(wallColumnPos);

                CreateRoom(i, j);
            }
            // 造最后一列柱子
            wallColumnPos.z = BuildColumn * 5;
            CreateWallColumn(wallColumnPos);

        }
        // 造最后一行柱子
        wallColumnPos.x = BuildRow * 5;
        for (int j = 0; j < BuildColumn; j++)
        {
            wallColumnPos.z = j * 5;
            CreateWallColumn(wallColumnPos);
        }
        wallColumnPos.z = BuildColumn * 5;
        CreateWallColumn(wallColumnPos);
    }
    // 砸墙
    public void BreakWall()
    {
        // 设置起始房间
        Vector2 startPos = Vector2.zero;
        RoomDict[startPos.ToString()].IsInit = true;
        Vector2 pos = startPos;
        // 砸墙：当所有房间都去过时，才跳出循环
        while (RoomDict.Any(r => !(r.Value.IsInit)))
        {
            Vector2[] availablePos = GetAvailableRoomPos(pos);
            // 找下一步可以移动所有房间
            if (availablePos.Length > 0)
            {
                // 随机选择一个房间
                Vector2 targetRoom = availablePos[Random.Range(0, availablePos.Length)];
                // 判断目标房间与当前房间坐标
                // 目标房间在上
                if (targetRoom.y > pos.y)
                {
                    // 删除目标房间的下面的墙
                    Destroy(RoomDict[targetRoom.ToString()].transform.GetChild(2).gameObject);
                }
                // 目标房间在右
                else if (targetRoom.x > pos.x)
                {
                    // 删除目标房间的左面的墙
                    Destroy(RoomDict[targetRoom.ToString()].transform.GetChild(1).gameObject);
                }
                // 目标房间在下
                else if (targetRoom.y < pos.y)
                {
                    // 删除起点房间的下面的墙
                    Destroy(RoomDict[pos.ToString()].transform.GetChild(2).gameObject);
                }
                // 目标房间在左
                else
                {
                    // 删除起点房间的左面的墙
                    Destroy(RoomDict[pos.ToString()].transform.GetChild(1).gameObject);
                }
                // 移动到目标房间，进行下一次循环
                pos = targetRoom;
                RoomDict[targetRoom.ToString()].IsInit = true;
            }
            // 找不到就传送到任意一个 与没有去过的房间相邻 的 已经去过的房间
            else
            {
                List<Room> rl = RoomList.FindAll(r => (r.IsInit && r.NearUnInitRoom()));
                pos = rl.ElementAt(Random.Range(0, rl.Count)).Coordinate;
            }

        }
    }
    private Vector2[] GetAvailableRoomPos(Vector2 startPos)
    {
        var ret = new List<Vector2>();
        Room room;
        Vector2 top = new Vector2(startPos.x, startPos.y + 1);
        if (RoomDict.TryGetValue(top.ToString(), out room) && !room.IsInit)
        {
            ret.Add(top);
        }
        Vector2 right = new Vector2(startPos.x + 1, startPos.y);
        if (RoomDict.TryGetValue(right.ToString(), out room) && !room.IsInit)
        {
            ret.Add(right);
        }
        Vector2 bottom = new Vector2(startPos.x, startPos.y - 1);
        if (RoomDict.TryGetValue(bottom.ToString(), out room) && !room.IsInit)
        {
            ret.Add(bottom);
        }
        Vector2 left = new Vector2(startPos.x - 1, startPos.y);
        if (RoomDict.TryGetValue(left.ToString(), out room) && !room.IsInit)
        {
            ret.Add(left);
        }
        return ret.ToArray();
    }
    // 创建一堵墙
    private void CreateWallColumn(Vector3 pos)
    {
        var wallColumn = Instantiate(WallColumnPrefab, pos, Quaternion.identity);
        wallColumn.transform.SetParent(WallColumnParent.transform);
    }
    // 创建一个房间
    private void CreateRoom(int x, int z)
    {
        Vector3 pos = new Vector3(x * 5 + 2.5f, 0, z * 5 + 2.5f);
        var room = Instantiate(RoomPrefab, pos, Quaternion.identity);

        var coordinate = new Vector2(x, z);
        var roomScript = room.GetComponent<Room>();
        roomScript.Coordinate = coordinate;
        room.transform.SetParent(RoomParent.transform);

        RoomDict.Add(coordinate.ToString(), roomScript);
        RoomList.Add(roomScript);

        // 生成左面墙壁
        var leftWall = Instantiate(WallPrefab, room.transform);
        leftWall.transform.eulerAngles = new Vector3(0, 90, 0);
        leftWall.transform.position = room.transform.position + new Vector3(-2.5f, wallYOffset, 0);

        // 生成下面墙壁
        var bottomWall = Instantiate(WallPrefab, room.transform);
        bottomWall.transform.position = room.transform.position + new Vector3(0, wallYOffset, -2.5f);

        // 生成右面墙壁
        if (x == BuildRow - 1)
        {
            var rightWall = Instantiate(WallPrefab, room.transform);
            rightWall.transform.eulerAngles = new Vector3(0, -90, 0);
            rightWall.transform.position = room.transform.position + new Vector3(2.5f, wallYOffset, 0);
        }

        // 生成上面墙壁
        if (z == BuildColumn - 1)
        {
            var topWall = Instantiate(WallPrefab, room.transform);
            topWall.transform.position = room.transform.position + new Vector3(0, wallYOffset, 2.5f);
        }
    }
}
